import { Injectable } from '@nestjs/common';
import { EntityManager } from 'typeorm';
import { Article } from './entities/article.entity';
import { RedisService } from 'src/redis/redis.service';

@Injectable()
export class ArticleService {
  constructor(
    private readonly entityManager: EntityManager,
    private readonly redisService: RedisService,
  ) {}
  findOne(id: number) {
    return this.entityManager.findOne(Article, {
      where: {
        id,
      },
    });
  }

  async readAritcle(id: number, userId: number) {
    const articleResByRedis = await this.redisService.hashGet(`article:${id}`);

    if (!articleResByRedis?.viewCount) {
      await this.entityManager.update(
        Article,
        { id },
        { viewCount: () => 'viewCount + 1' },
      );
      const article = await this.findOne(id);

      await this.redisService.hashSet(
        `article:${id}`,
        {
          viewCount: article.viewCount,
          likeCount: article.likeCount,
          collectCount: article.collectCount,
        },
        60 * 60 * 24,
      );

      // 如果redis里面没有存储该文章则增加一个固定时间过期的标记，防止频繁访问导致文章访问量增加
      // 这里设置了20秒过期，其实可以自定义设置缓存时间
      await this.redisService.set(`userId:${userId}:article:${id}`, '1', 20);

      return article;
    }

    // 如果redis里面有存储过期标志则直接返回
    const flag = await this.redisService.get(`userId:${userId}:article:${id}`);
    if (flag) return +articleResByRedis.viewCount;

    articleResByRedis.viewCount = +articleResByRedis.viewCount + 1;
    await this.redisService.hashSet(`article:${id}`, {
      ...articleResByRedis,
    });

    // 重新设置过期标志
    await this.redisService.set(`userId:${userId}:article:${id}`, '1', 20);

    return +articleResByRedis.viewCount;
  }

  async refreshToDB() {
    const kes = await this.redisService.getKeys('article:*');

    for (let i = 0; i < kes.length; i++) {
      const articleResByRedis = await this.redisService.hashGet(kes[i]);
      const id = kes[i].split(':')[1];
      this.entityManager.update(
        Article,
        { id },
        { viewCount: +articleResByRedis.viewCount },
      );
    }
  }
}
